using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Drawing;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using ctsu.Admin.Forms;
using ctsu.BaseForms;
using ctsu.Shared;
using Microsoft.Practices.EnterpriseLibrary.Data;

using Syncfusion.Windows.Forms.Tools;
using ctsu.CustomControls;
using ctsu.Data;

namespace ctsu.Admin.BusLogic
{
	public class BLFormBaseImpl : IBLFormBase
	{
		#region control references
		protected FormBase _form;
		protected FormMain _formMain;
		protected FormInfoBase _formInfo;
		protected DataTable _tableSchema;
		protected Hashtable _gridBLs;

		protected ctsu.Security.Permission _formSecurity;
		protected IFieldContextManager _fcManager;
		protected EditMode _formMode;
		protected Hashtable _configData;
		protected int _currentPrimaryID;

		protected FormGrid _formGrid;
		protected CheckBox _chkCarry;

		protected bool _doFieldValidate = false;
		protected bool _doSummaryValidate = false;
		protected bool _isClosing = false;
		#endregion control references

		public event BusinessLogicEvents.BLGridViewEventHandler GridView;
		public event BusinessLogicEvents.BLTableChangeEventHandler TableChange;
		public event BusinessLogicEvents.BLRequestIDFromOtherFormHandler RequestIDFromTarget;
		protected bool IsSearchVisible = false;

		public EditMode FormMode
		{
			get { return this._formMode; }
		}
		public int CurrentPrimaryID
		{
			get { return _currentPrimaryID; }
		}

		#region properties
		public Icon FormIcon
		{
			set { _form.Icon = value; }
		}

		public IFieldContextManager FieldContextManager
		{
			get { return _fcManager; }
			set { _fcManager = value; }
		}

		public FormInfoBase FormInfo
		{
			get { return this._formInfo; }
			set { this._formInfo = value; }
		}

		public FormBase Form
		{
			get { return this._form; }
			set { this._form = value; }
		}

		public DataTable TableSchema
		{
			get { return this._tableSchema; }
			set { this._tableSchema = value; }
		}

		public ctsu.Security.Permission FormSecurity
		{
			get { return _formSecurity; }
			set { _formSecurity = value; }
		}

		public Hashtable ConfigData
		{
			get { return _configData; }
			set { _configData = value; }
		}
		#endregion properties

		public BLFormBaseImpl(FormMain formMain, FormBase form, FormInfoBase formInfo, DataTable tableSchema, ctsu.Security.Permission formSecurity, Hashtable configData)
		{
			this._formMain = formMain;
			this._form = form;
			this._formInfo = formInfo;
			this._tableSchema = tableSchema;
			this._formSecurity = formSecurity;
			this._configData = configData;
			this._formMain.ReturnIDToRequester += new ctsu.BaseForms.BusinessLogicEvents.BLReturnIDToRequestingFormHandler(this.OnReturnIDToRequestingForm);
			this._form.Activated += new EventHandler(_form_Activated);
		}

		#region initializing
		public virtual void _form_Activated(object sender, EventArgs e)
		{
			Console.WriteLine("_form_Activated: " + this._form.Name);
		}

		public virtual bool Initialize()
		{
			Console.WriteLine("FormBLBase Initialize");
			//create instance of fc manager and hook events
			_fcManager = new FieldContextManager(this);

			//subscribe to fieldContext Manager events
			//this allows exstensibility for the field contexts
			_fcManager.OnAfterHookEvents += new ctsu.BaseForms.BusinessLogicEvents.BusinessEventNotifyHandler(_vcManager_OnAfterHookEvents);
			_fcManager.OnAfterCreateFieldContexts += new ctsu.BaseForms.BusinessLogicEvents.BusinessEventNotifyHandler(_fcManager_OnAfterCreateFieldContexts);
			_fcManager.OnAfterBindFieldContextsToControls += new ctsu.BaseForms.BusinessLogicEvents.BusinessEventNotifyHandler(_fcManager_OnAfterBindFieldContextsToControls);
			_fcManager.OnAfterLoadMetaDataEvents += new ctsu.BaseForms.BusinessLogicEvents.BusinessEventNotifyHandler(_fcManager_OnAfterLoadMetaDataEvents);

			//call the major methods on fieldContextManager
			_fcManager.CreateFieldContexts(_tableSchema, null, this._formInfo.UniqueField);
			_fcManager.BindFieldContextsToControls();
			_fcManager.LoadMetadata();
			_fcManager.HookEvents();

			FormOptions.OnOptionsChanged += new ctsu.Admin.Forms.FormOptions.OptionsChangedHandler(FormOptions_OnOptionsChanged);

			//set config settings 
			if (this._configData.Count == 0)
				;
			else
			{
				this._doFieldValidate = (bool)this._configData["FieldValidate"];
				this._doSummaryValidate = (bool)this._configData["SummaryValidate"];
			}

			this._formMode = EditMode.Load;
			//initialize lookups
			if (_formInfo.Lookups.Length > 0)
				if (!FillLookups())
					return false;
			if (_formInfo.SpecialLookups.Count > 0)
				if (!FillSpecialLookups())
					return false;

			//initialize grids if any
			this._gridBLs = new Hashtable();
			if (_formInfo.GridMeta.Count > 0)
			{
				if (!InitializeGrids())
					return false;
			}

			this._chkCarry = (CheckBox)Forms.Utils.GetControlByName("chkCarry", this._form.Controls);
			if (!_formInfo.HasCarry)
				this._chkCarry.Visible = false;

			//enable new button if permission allows
			if (this._formSecurity != ctsu.Security.Permission.ReadOnly)
				this._form.btnNew.Enabled = true;

			this._form.Text = this._formInfo.Name;
			SetFormMode(EditMode.Empty);

			return true;
		}

		internal bool InitializeGrids()
		{
			foreach (FormGridMeta fgm in _formInfo.GridMeta.Values)
			{
				if (!InitializeGrid(fgm))
					return false;
			}
			return true;
		}

		protected virtual bool InitializeGrid(FormGridMeta fgm)
		{
			UserGrid uGrd = (UserGrid)Forms.Utils.GetControlByName(fgm.GridName, this._form.Controls);

			//FormGridMeta formGridMeta, UserGrid uGrid, FormInfoBase formInfo, FormBase form
			Type[] argTypes = new Type[4];
			argTypes[0] = typeof(FormGridMeta);
			argTypes[1] = typeof(UserGrid);
			argTypes[2] = typeof(FormInfoBase);
			argTypes[3] = typeof(FormBase);

			object[] args = new object[4];
			args[0] = fgm;
			args[1] = uGrd;
			args[2] = _formInfo;
			args[3] = _form; //security permission

			//invoke creation of bl
			Type grdBL = Type.GetType("ctsu.Admin.BusLogic." + fgm.BusinessLogicClassName);

			ConstructorInfo info = grdBL.GetConstructor(argTypes);
			IBLFormGridBase fgbl = (IBLFormGridBase)info.Invoke(args);
			fgbl.GridColumnValueChanged += new ctsu.BaseForms.BusinessLogicEvents.BLGridColumnValueChangedHandler(fgbl_GridColumnValueChanged);
			fgbl.GridValidateError += new ctsu.BaseForms.BusinessLogicEvents.BLGridValidateErrorEventHandler(fgbl_GridValidateError);

			//BLFormGridBaseImpl fgbl = new BLFormGridBaseImpl(fgm, uGrd, this._formInfo, this._form);
			if (!fgbl.Initialize())
				return false;
			_gridBLs.Add(fgm.GridName, fgbl);
			return true;
		}


		protected virtual bool FillSpecialLookups()
		{
			StringBuilder sb = new StringBuilder();
			try
			{
				foreach (SpecialLookup sl in _formInfo.SpecialLookups.Values)
				{
					Control ctl = ctsu.Admin.Forms.Utils.GetControlByName(sl.FieldName, this._form.Controls);
					if (sl.GridName.Length > 0)
						continue;
					ctsu.Admin.Forms.Utils.LoadCbo(sl, ctl);
				}

			}
			catch (Exception ex)
			{
				sb.Append("Could not load special lookups!");
				sb.Append(Environment.NewLine);
				sb.Append("Error message: " + ex.Message);
				//bool b = ////ExceptionPolicy.HandleException(ex, "Exception Policy");
				MessageBox.Show(this._form, sb.ToString(), "Loading Special Lookups Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return false;
			}
			return true;
		}

		internal bool FillLookups()
		{
			StringBuilder sb = new StringBuilder();
			//_htPickLists = new Hashtable();
			string[] aLups = this._formInfo.Lookups.Split(',');

			try
			{
				foreach (string s in aLups)
				{
					string table = s + "_L";
					Control ctl = ctsu.Admin.Forms.Utils.GetControlByName(s, this._form.Controls);
					if (ctl.GetType() == typeof(Syncfusion.Windows.Forms.Tools.ComboBoxAutoComplete))
						ctsu.Admin.Forms.Utils.LoadCbo((Syncfusion.Windows.Forms.Tools.ComboBoxAutoComplete)ctl, table, true);
					else
						ctsu.Admin.Forms.Utils.LoadCbo(ctl, table, true);
				}
			}
			catch (Exception ex)
			{
				sb.Append("Could not load lookups!");
				sb.Append(Environment.NewLine);
				sb.Append("Error message: " + ex.Message);
				//bool b = ////ExceptionPolicy.HandleException(ex, "Exception Policy");
				MessageBox.Show(this._form, sb.ToString(), "Loading Lookups Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return false;
			}
			return true;
		}
		#endregion initializing

		#region form mode
		public virtual void SetFormMode(EditMode newMode)
		{
			EditMode oldMode = this._formMode;
			switch (oldMode)
			{
				case EditMode.Load:
					if (newMode == EditMode.Read)
					{
						this._form.pnl2.Enabled = true;
						SetControlsEnabled(false);
						SetNavigationEnabled(newMode);
					}
					if (newMode == EditMode.New)
					{
						this._form.pnl2.Enabled = true;
						SetControlsEnabled(true);
						SetNavigationEnabled(newMode);
					}
					if (newMode == EditMode.Empty)
					{
						SetControlsEnabled(false);
						SetNavigationEnabled(newMode);
						this._form.pnl2.Enabled = false;
					}
					break;

				case EditMode.New:
					if (newMode == EditMode.Read)
					{
						SetControlsEnabled(false);
						SetNavigationEnabled(newMode);
					}
					break;

				case EditMode.Edit:
					if (newMode == EditMode.Read)
					{
						SetControlsEnabled(false);
						SetNavigationEnabled(newMode);
					}
					break;

				case EditMode.Read:
					if (newMode == EditMode.Edit)
					{
						SetControlsEnabled(true);
						SetNavigationEnabled(newMode);
					}
					break;
			}

			this._formMode = newMode;
			this._form.Mode.Text = newMode.ToString();
		}

		protected virtual void SetControlsEnabled(bool enable)
		{
			Control ctl;

			foreach (FieldContext fc in _fcManager.Items)
			{
				ctl = fc.Control;
				if (ctl == null)
					continue;
				if (fc.Column.ColumnName == "ID")
					continue;

				ctl.Enabled = enable;
			}

			SetGridsEnabled(enable);

		}

		protected virtual void SetGridsEnabled(bool enable)
		{
			foreach (BLFormGridBaseImpl fgbl in _gridBLs.Values)
			{
				fgbl.SetEnabled(enable);
			}
		}

		private void SetNavigationEnabled(EditMode mode)
		{
			this._form.btnSearch.Enabled = false;
			this._form.btnNew.Enabled = false;
			this._form.btnEdit.Enabled = false;
			this._form.btnRemove.Enabled = false;
			this._form.btnSave.Enabled = false;
			this._form.btnCancel.Enabled = false;

			switch (mode)
			{
				case EditMode.Read:
					//no dependance on security
					if (!IsSearchVisible)
						this._form.btnSearch.Enabled = true;

					//security dependant
					if (this._formSecurity == ctsu.Security.Permission.ReadWrite)
					{
						this._form.btnNew.Enabled = true;
						this._form.btnEdit.Enabled = true;
					}

					if (this._formSecurity == ctsu.Security.Permission.Administrator)
					{
						this._form.btnNew.Enabled = true;
						this._form.btnEdit.Enabled = true;
						this._form.btnRemove.Enabled = true;
					}
					break;

				case EditMode.New:
					this._form.btnCancel.Enabled = true;
					break;
				case EditMode.Edit:
					this._form.btnCancel.Enabled = true;
					break;
				case EditMode.Empty:
					if (!IsSearchVisible)
						this._form.btnSearch.Enabled = true;
					if (this._formSecurity == ctsu.Security.Permission.ReadWrite ||
						this._formSecurity == ctsu.Security.Permission.Administrator)
						this._form.btnNew.Enabled = true;
					break;

			}
		}
		#endregion form mode

		public virtual void FireRequestIDFromTarget(object sender, MessageQEventArgs e)
		{
			if (this.RequestIDFromTarget != null)
				this.RequestIDFromTarget(sender, e);
		}

		protected virtual void OnReturnIDToRequestingForm(object sender, BLReturnIDEventArgs e)
		{

		}

		#region grid view
		public void ShowGrid()
		{
			string sql = "";
			string gridName = "grd" + _formInfo.TableName;
			FormMain fm = (FormMain)_form.MdiParent;
			FormDockingManager fdm = fm.DockManager;

			if (this._formGrid != null)
			{
				//if its not null then we have already been thru here
				//so just make sure the grid is the active one
				fdm.ActivateDockControl(gridName);
				return;
			}

			//does the grid exist
			if (fdm.DockControlExists(gridName))
			{
				//need to get a reference to the formGrid
				_formGrid = (FormGrid)fdm.GetDockControl(gridName);

				//make sure it is visible
				if (!fdm.IsDockControlVisible(gridName))
					fdm.SetDockControlVisibility(gridName, true);
				//then activate it
			}
			else //create it		
			{
				sql = "SELECT * FROM " + this._formInfo.TableName +
					" ORDER BY ID";
				_formGrid = new FormGrid(sql, this._form, this._formInfo.TableName);
				_formGrid.Text = gridName;
				BLGridViewEventArgs e = new BLGridViewEventArgs(gridName, _formGrid);

				//this will dock the new grid
				if (this.GridView != null)
					GridView(this, e);
				_formGrid.Show();

			}

			//call back for user changing the current row of the grid
			//this is used for grid tracking
			_formGrid.FormGridRowChange += new FormGrid.FormGridRowChangeEventHandler(this.FormGridRowChange);

			//this is used to set the grid reference to null
			_formGrid.Closing += new CancelEventHandler(_formGrid_Closing);

			//this is used to refresh the data in the grid
			TableChange += new ctsu.BaseForms.BusinessLogicEvents.BLTableChangeEventHandler(_formGrid.OnBLTableChange);
		}

		private void _formGrid_Closing(object sender, CancelEventArgs e)
		{
			_formGrid = null;
		}

		private void FormGridRowChange(object sender, FormGridRowChangeEventArgs e)
		{
			Console.WriteLine("Grid cur id: " + e.ID.ToString());
			if (!this._form.Visible)
				return;
			if (this._form.chkGridTracking.Checked && (this._formMode == EditMode.Read || this._formMode == EditMode.Empty))
			{
				if (this.GetData(e.ID))
				{
					if (this.FormMode == EditMode.Load)
						SetFormMode(EditMode.Read);
				}
			}
		}
		#endregion grid view

		#region form close
		public virtual void Exit()
		{
			this._form.Close();
		}

		public virtual bool Closing()
		{
			if (this._fcManager.IsRowDirty && !_isClosing)
			{
				if (MessageBox.Show(_form, "Do you want to exit without saving changes?", "Confirm Exit",
					MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
				{
					return true;
				}
			}

			//			if(this.DataAcc.Connection.State == ConnectionState.Open)
			//				this.DataAcc.Connection.Dispose();

			this.ClearCarryData();

			//			if(_formInfo.MenuItm != null)
			//				_formInfo.MenuItm.Enabled = true;
			//			if(_formInfo.GroupViewItm != null)
			//				_formInfo.GroupViewItm.Enabled = true;

			return false;
		}
		#endregion form close

		public virtual void GenericClick(System.Windows.Forms.Control sender)
		{
		}

		public virtual void CarryNewClicked(object sender)
		{
		}

		protected virtual void GetCarryData()
		{
		}

		protected virtual void ClearCarryData()
		{
		}

		public virtual void GenericDoubleClick(System.Windows.Forms.Control sender)
		{
			//Console.WriteLine("OnGenericClick:Decendent, sender: " + sender.Name);
		}

		public virtual bool Remove()
		{
			return true;
		}

		#region cancel
		public virtual void Cancel()
		{
			bool confirmCancel = false;

			if (_form.btnSave.Enabled)
			{
				if (MessageBox.Show(_form, "Do you want to cancel without saving changes?", "Confirm Cancel",
					MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
				{
					confirmCancel = true;
				}
			}
			else
				//don't need confirm
				confirmCancel = true;

			if (!confirmCancel)
				return;

			//check config setting
			bool shouldClose = (bool)this._configData["CloseOnCancel"];
			if (shouldClose)
			{
				this._isClosing = true;
				this._form.Close();
			}
			else
			{
				//reset data to original vlaues				
				ResetToOriginal();
				ResetGrids();
			}
		}

		protected virtual void ResetGrids()
		{
			foreach (BLFormGridBaseImpl fgbl in _gridBLs.Values)
				fgbl.Reset(this._formMode, _currentPrimaryID);
		}

		protected virtual void ResetToOriginal()
		{
			this._formMode = EditMode.Load;

			if (this._fcManager.CurrentRow.RowState == DataRowState.Added || this._fcManager.CurrentRow.RowState == DataRowState.Deleted)
			{
				this._fcManager.DbTable = null;
				this._fcManager.CurrentRow = null;
				ClearAllControls();
				_form.pnl2.Enabled = false;
				SetFormMode(EditMode.Empty);
			}
			else
			{
				this._fcManager.CurrentRow.RejectChanges();
				DisplayData();
				SetFormMode(EditMode.Read);
			}
		}

		protected virtual void ClearAllControls()
		{
			string fieldType;
			string controlType;
			Control ctl;

			foreach (FieldContext fc in _fcManager.Items)
			{
				ctl = fc.Control;
				if (ctl == null)
					continue;
				//TODO - what if key needs to be displayed
				//what if key is not named ID
				//				if(fc.Column.ColumnName == "ID")
				//					continue;

				if (fc.ErrorControl != null)
					this._form.errP.SetError(fc.ErrorControl, "");
				fieldType = fc.Column.DataType.ToString();
				controlType = ctl.GetType().ToString();

				switch (controlType)
				{
					case "System.Windows.Forms.TextBox":
						ctl.Text = "";
						break;

					case "Syncfusion.Windows.Forms.Tools.DateTimePickerAdv":
						DateTimePickerAdv dtp = (DateTimePickerAdv)ctl;
						dtp.IsNullDate = true;
						break;

					case "System.Windows.Forms.CheckBox":
						CheckBox chk = (CheckBox)ctl;
						chk.Checked = false;
						break;

					case "System.Windows.Forms.ComboBox":
						ComboBox cbo = (ComboBox)ctl;
						cbo.SelectedIndex = -1;
						cbo.SelectedIndex = -1;
						break;
				}
			}
		}
		#endregion cancel

		#region #region search get and display
		public virtual void Search(object sender)
		{
			Control ctl = (Control)sender;

			ctl.Enabled = false;
			Cursor.Current = Cursors.WaitCursor;

			string key = "";
			//if ctl name is btnSearch then use the form table
			if (ctl.Name == "btnSearch")
				key = this.FormInfo.TableName;
			else
				key = ctl.Name;

			SearchInfo si = (SearchInfo)this.FormInfo.SearchFormInfo[key];
			if (si == null)
			{
				MessageBox.Show("Search criteria is not defined.", "Search Criteria Not Fount",
					MessageBoxButtons.OK, MessageBoxIcon.Stop);
				ctl.Enabled = true;
				return;
			}

			FormSearch fs = new FormSearch();

			//get the search fields			
			foreach (ReportColumn rc in si.SearchFields)
				fs.SearchFields.Items.Add(rc);

			//design list view for result fields			
			ListView lvw = fs.SearchResults;
			lvw.Columns.Clear();
			if (lvw != null)
			{
				foreach (ReportColumn rc in si.SearchResultCols)
				{
					ColumnHeader ch = new ColumnHeader();
					ch.Text = rc.DisplayName;

					//get width from schema
					//					dc = si.TableSchema.Columns[rc.FieldName];
					//					fieldType = dc.DataType.ToString();

					//auto size column based on display text
					ch.Width = -2;
					lvw.Columns.Add(ch);
				}
			}


			//SearchController sc = new SearchController(fs, si);
			//create an instance of the form
			Type scType = Type.GetType("ctsu.Admin.BusLogic." + si.SearchController);
			if (scType == null)
			{
				MessageBox.Show("This function is not defined yet");
				ctl.Enabled = true;
				return;
			}

			Type[] argTypes = new Type[2];
			argTypes[0] = typeof(FormSearch);
			argTypes[1] = typeof(SearchInfo);

			object[] args = new object[2];
			args[0] = fs;
			args[1] = si;

			ConstructorInfo info = scType.GetConstructor(argTypes);
			ISearchController sc = (ISearchController)info.Invoke(args);

			fs.Controller = sc;
			fs.Owner = this._form;
			sc.ItemSelected += new ctsu.BaseForms.BusinessLogicEvents.BLSelectedItemEventHandler(sc_ItemSelected);
			fs.Closing += new CancelEventHandler(fs_Closing);
			IsSearchVisible = true;
			fs.Show();
		}

		private void sc_ItemSelected(object sender, BLReturnIDEventArgs e)
		{
			if (e.ID > 0)
			{
				Console.WriteLine("Selected ID: " + e.ID.ToString());
				if (GetData(e.ID))
				{
					if (this.FormMode == EditMode.Load)
						SetFormMode(EditMode.Read);
				}
			}
		}

		private void fs_Closing(object sender, CancelEventArgs e)
		{
			IsSearchVisible = false;
			this._form.btnSearch.Enabled = true;
		}

		public virtual bool GetData(int id)
		{
			StringBuilder sb = new StringBuilder();
			//this works only if there is one key and it is numeric
			//and -1 is not a possible vaule
			string keyFieldName = (string)this._fcManager.TableKeysOrdered[0];
			string sql = "SELECT * FROM " + this._formInfo.TableName +
				" WHERE " + keyFieldName + " =" + id;

			//SqlConnection conn = LoginForm.GetSqlConnection();			
			try
			{
				DataSet ds = DataAccess.GetDataSet(sql);
				DataTable dt = ds.Tables[0];
				if (dt.Rows.Count == 1)
				{
					_fcManager.DbTable = dt;
					_fcManager.CurrentRow = dt.Rows[0];
					this._formMode = Shared.EditMode.Load;
					this._currentPrimaryID = id;
					DisplayData();
					GetGridData(id);
				}
				this.CarryNewClicked(this._chkCarry);

				return true;
			}
			catch (Exception ex)
			{
				sb.Append("Error in retrieving data");
				sb.Append(Environment.NewLine);
				sb.Append(ex.Message);
				//bool b = ////ExceptionPolicy.HandleException(ex, "Exception Policy");
				MessageBox.Show(this._form, sb.ToString(), "Get Data Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
				this.ClearCarryData();
				return false;
			}
			finally
			{
				//if(conn != null)
				//    conn.Dispose();
			}
		}
		protected virtual bool GetGridData(int id)
		{
			if (this._gridBLs != null)
			{
				foreach (BLFormGridBaseImpl fgbl in this._gridBLs.Values)
				{
					if (!fgbl.GetData(id))
					{
						//TODO - need to do more here for exception							
						MessageBox.Show("GetGridData Exception");
						return false;
					}
				}
			}
			return true;
		}

		public virtual void InitializeEmptyControls()
		{
			string controlType;
			Control ctl;

			foreach (FieldContext fc in _fcManager.Items)
			{
				ctl = fc.Control;
				if (ctl == null)
					continue;

				controlType = ctl.GetType().ToString();
				if (this._formMode != EditMode.Empty)
					return;

				switch (controlType)
				{
					case "Syncfusion.Windows.Forms.Tools.DateTimePickerAdv":
						DateTimePickerAdv dtp = (DateTimePickerAdv)ctl;
						dtp.Value = DateTime.Today;
						dtp.IsNullDate = true;
						break;

					case "System.Windows.Forms.ComboBox":
						ComboBox cbo = (ComboBox)ctl;
						cbo.SelectedIndex = -1;
						break;
				}
			}
		}

		public virtual void DisplayData()
		{
			string fieldType;
			string controlType;
			string sVal;
			Control ctl;

			foreach (FieldContext fc in _fcManager.Items)
			{
				ctl = fc.Control;
				if (ctl == null)
					continue;
				//				if(fc.Column.ColumnName == "ID")
				//					continue;

				fieldType = fc.Column.DataType.ToString();
				controlType = ctl.GetType().ToString();

				//disable controls while in read mode
				if (this._formMode == EditMode.Load)
					ctl.Enabled = false;
				else
					ctl.Enabled = true;

				_form.errP.SetError(ctl, "");
				switch (controlType)
				{
					case "System.Windows.Forms.MaskedTextBox":
						sVal = _fcManager.CurrentRow[fc.Column.ColumnName].ToString();
						ctl.Text = sVal;
						break;

					case "System.Windows.Forms.TextBox":
						//have to some thing here for numerics
						sVal = _fcManager.CurrentRow[fc.Column.ColumnName].ToString();
						ctl.Text = sVal;
						break;

					case "Syncfusion.Windows.Forms.Tools.DateTimePickerAdv":
						DateTimePickerAdv dtp = (DateTimePickerAdv)ctl;
						if (_fcManager.CurrentRow[fc.Column.ColumnName] is System.DBNull)
						{
							dtp.Value = DateTime.Today;
							dtp.IsNullDate = true;
						}
						else
						{
							dtp.IsNullDate = false;
							dtp.Value = (DateTime)_fcManager.CurrentRow[fc.Column.ColumnName];
						}
						break;

					case "System.Windows.Forms.CheckBox":
						CheckBox chk = (CheckBox)ctl;
						chk.Checked = false;
						if (_fcManager.CurrentRow[fc.Column.ColumnName] != System.DBNull.Value)
							chk.Checked = (bool)_fcManager.CurrentRow[fc.Column.ColumnName];
						break;

					case "System.Windows.Forms.ComboBox":
						ComboBox cbo = (ComboBox)ctl;
						if (_fcManager.CurrentRow[fc.Column.ColumnName] == System.DBNull.Value)
						{
							cbo.SelectedIndex = -1;
							cbo.SelectedIndex = -1;
						}
						else
							cbo.SelectedValue = (int)_fcManager.CurrentRow[fc.Column.ColumnName];
						break;
				}

			}
		}
		#endregion search get and display

		#region new
		public virtual void New()
		{
			StringBuilder sb = new StringBuilder();
			//this assures us of an empty table
			string sql = "SELECT * FROM " + this._formInfo.TableName +
				" WHERE 1=2";

			//SqlConnection conn = LoginForm.GetSqlConnection();
			try
			{
				DataSet ds = DataAccess.GetDataSet(sql);
				DataTable dt = ds.Tables[0];
				_fcManager.DbTable = dt;

				DataRow dr = dt.NewRow();
				dt.Rows.Add(dr);
				_fcManager.CurrentRow = dt.Rows[0];

				SetGridsNew();

				this._formMode = Shared.EditMode.Load;
				this._currentPrimaryID = -1;
				DisplayData();
				GetCarryData();
				GetDefaultData();

				SetFormMode(EditMode.New);
			}
			catch (Exception ex)
			{
				//bool b = ////ExceptionPolicy.HandleException(ex, "Exception Policy");
				sb.Append("Could not create new table.");
				sb.Append(Environment.NewLine);
				sb.Append("Error message: " + ex.Message);
				MessageBox.Show(this._form, sb.ToString(), "New Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return;
			}
			finally
			{
				//if(conn != null)
				//    conn.Dispose();
			}
		}

		protected virtual void GetDefaultData()
		{
			string fieldType;
			string controlType;
			Control ctl;
			StringBuilder sb = new StringBuilder();

			try
			{
				foreach (FieldContext fc in _fcManager.Items)
				{
					if (fc.DefaultValue == null)
						continue;

					ctl = fc.Control;
					if (ctl == null)
						continue;

					fieldType = fc.Column.DataType.ToString();
					controlType = ctl.GetType().ToString();

					switch (controlType)
					{
						case "System.Windows.Forms.TextBox":
							ctl.Text = fc.DefaultValue.ToString();
							break;

						case "Syncfusion.Windows.Forms.Tools.DateTimePickerAdv":
							DateTimePickerAdv dtp = (DateTimePickerAdv)ctl;
							dtp.IsNullDate = false;
							dtp.Value = Convert.ToDateTime(fc.DefaultValue);
							break;

						case "System.Windows.Forms.CheckBox":
							CheckBox chk = (CheckBox)ctl;
							chk.Enabled = Convert.ToBoolean(fc.DefaultValue);
							break;

						case "System.Windows.Forms.ComboBox":
							ComboBox cbo = (ComboBox)ctl;
							cbo.SelectedValue = Convert.ToInt32(fc.DefaultValue);
							break;
					}
				}
			}
			catch (Exception ex)
			{
				sb.Append("Error in setting default data");
				sb.Append(Environment.NewLine);
				sb.Append(ex.Message);
				sb.Append(Environment.NewLine);
				sb.Append(ctsu.Shared.Constants.NotifySupportImmediate);
				sb.Append(Environment.NewLine);
				sb.Append("You should be able to continue without any problems!");
				MessageBox.Show(this._form, sb.ToString(), "Get Data Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
				sb.Append("Form: " + this._form.Name);
				//bool b = ////ExceptionPolicy.HandleException(ex, "Exception Policy");
			}
		}

		protected virtual void SetGridsNew()
		{
			//notify the grids there is a new form record
			if (this._gridBLs != null)
			{
				foreach (BLFormGridBaseImpl bl in this._gridBLs.Values)
					bl.New();
			}
		}
		#endregion new

		public virtual void Edit()
		{
			SetFormMode(EditMode.Edit);
		}

		#region save
		public virtual bool Save()
		{
			StringBuilder sb = new StringBuilder();
			string message = "";

			//this is used as a parameter for table grid display
			DbTableChange tableChange = DbTableChange.Update;

			if (this._doSummaryValidate)
			{
				if (!VerifyAll())
					return false;
				if (!VerifyGrids())
					return false;
			}

			Console.WriteLine("RowState brfore save: " + this._fcManager.CurrentRow.RowState.ToString());
			Database db = DatabaseFactory.CreateDatabase();
			using (DbConnection conn = db.CreateConnection())
			{
				try
				{
					conn.Open();
					DbTransaction trans = conn.BeginTransaction();

					if (_formMode == EditMode.New)
					{
						if (CheckDuplicate())
							return false;
						if (CheckWarning())
							return false;
						tableChange = DbTableChange.Insert;
						if (!SaveNew(out message, db, trans))
						{
							trans.Rollback();
							sb.Append("New record for " + this._formInfo.Name + " could not be saved.");
							sb.Append(Environment.NewLine);
							sb.Append("Error: " + message);
							MessageBox.Show(this._form, sb.ToString(), "Save Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
							return false;
						}

					}
					else if (_formMode == EditMode.Edit)
					{
						if (!Update(out message, db, trans))
						{
							trans.Rollback();
							sb.Append("Update for " + this._formInfo.Name + " could not be saved.");
							sb.Append(Environment.NewLine);
							sb.Append("Error: " + message);
							MessageBox.Show(this._form, sb.ToString(), "Save Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
							return false;
						}
					}

					if (this._gridBLs != null)
					{
						if (!SaveGrids(out message, db, trans))
						{
							trans.Rollback();
							sb.Append("Grid data " + this._formInfo.Name + " could not be saved.");
							sb.Append(Environment.NewLine);
							sb.Append("Error: " + message);
							MessageBox.Show(this._form, sb.ToString(), "Save Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
							return false;
						}
					}

					trans.Commit();
					ResetGrids();
					//confirmation dialog
					MessageBox.Show("Record was saved.", "Save Confirmation",
						MessageBoxButtons.OK, MessageBoxIcon.Information);

					bool shouldClose = (bool)this._configData["CloseOnSave"];

					if (shouldClose)
					{
						this._isClosing = true;
						this._form.Close();
					}
					else
					{
						this._fcManager.CurrentRow.AcceptChanges();
						SetGridsAcceptChanges();
						SetFormMode(EditMode.Read);
					}
					BLTableChangeAdvEventArgs args = new BLTableChangeAdvEventArgs(this._formInfo.TableName, tableChange, this._currentPrimaryID - 1);

					this.TableChange(this._form, args);
					Console.WriteLine("RowState after save: " + this._fcManager.CurrentRow.RowState.ToString());
					this.CarryNewClicked(_chkCarry);

					return true;
				}
				catch (Exception ex)
				{
					//bool b = ////ExceptionPolicy.HandleException(ex, "Exception Policy");
					sb.Append("Form could not be saved.");
					sb.Append(Environment.NewLine);
					sb.Append("Error message: " + ex.Message);
					MessageBox.Show(this._form, sb.ToString(), "Save Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
					return false;
				}
			}
		}

		protected virtual void FireTableChange(BLTableChangeAdvEventArgs args)
		{
			this.TableChange(this._form, args);
		}

		protected virtual bool CheckDuplicate()
		{
			return false;
		}

		protected virtual bool CheckWarning()
		{
			return false;
		}

		protected void FireTableChange(DbTableChange tableChange)
		{
			BLTableChangeAdvEventArgs args = new BLTableChangeAdvEventArgs(this._formInfo.TableName, tableChange, this._currentPrimaryID - 1);

			this.TableChange(this._form, args);
		}

		protected virtual bool VerifyGrids()
		{
			if (this._gridBLs != null)
			{
				foreach (BLFormGridBaseImpl fgbl in this._gridBLs.Values)
					if (!fgbl.VerifyGrid())
						return false;
			}
			return true;
		}

		protected virtual void SetGridsAcceptChanges()
		{
			foreach (BLFormGridBaseImpl bl in this._gridBLs.Values)
			{
				bl.AcceptChanges();
			}
		}

		protected virtual bool SaveGrids(out string message, Database db, DbTransaction trans)
		{
			message = "";
			foreach (BLFormGridBaseImpl bl in this._gridBLs.Values)
			{
				if (!bl.Save(this._currentPrimaryID, out message, db, trans))
					return false;
			}
			return true;
		}

		protected virtual bool SaveNew(out string message, Database db, DbTransaction trans)
		{
			message = "";
			bool isSuccess = false;

			//sql insert
			string[] exclude = { "ModifiedBy", "ModifiedWhen" };
			//autoIncrement field is not included
			string sqlIns = Forms.DataUtils.GetSqlInsertStatment(this._tableSchema, exclude, this._formInfo.TableName);

			//sql parameters
			SqlParameter[] aParams = Forms.DataUtils.GetSqlParameters(exclude, false, this._tableSchema);

			//assign parameters
			AssignParameters(aParams);
			try
			{
				DbCommand cmd = db.GetSqlStringCommand(sqlIns);
				DataAccess.AddParamArrayToDbCommand(cmd, aParams);

				int i = db.ExecuteNonQuery(cmd, trans);
				//get key id for new row
				SetKeyValues(db, trans);
				isSuccess = true;
			}
			catch (Exception ex)
			{
				isSuccess = false;
				//bool b = ////ExceptionPolicy.HandleException(ex, "Exception Policy");
				if (ex.Message.StartsWith("Violation of UNIQUE KEY"))
				{
					string field = this._fcManager.GetUniqueFieldNotKey();
					FieldContext fc = (FieldContext)this._fcManager.Item(field);
					string val = fc.CurrentValue.ToString();

					StringBuilder sb = new StringBuilder();
					sb.Append("Field: " + field + " ");
					sb.Append("must be unique.");
					sb.Append(Environment.NewLine);
					sb.Append("Value: " + val + " already exists in the table.");
					message = sb.ToString();
				}
				else
					message = ex.Message;
			}
			return isSuccess;
		}

		protected void SetKeyValues(Database db, DbTransaction trans)
		{
			//TODO - this is setup for autoIncrement keys only
			//need to something if otherwise
			foreach (string s in this._fcManager.TableKeysOrdered)
			{
				DataColumn dc = (DataColumn)this._fcManager.TableKeys[s];
				if (dc.AutoIncrement)
				{
					object o = db.ExecuteScalar(trans, CommandType.Text, "SELECT @@IDENTITY");
					this._fcManager.CurrentRow[s] = o;
					FieldContext fc = (FieldContext)this._fcManager.Item(s);
					fc.Control.Text = o.ToString();
					this._currentPrimaryID = Convert.ToInt32(o);
					//there can be only 1 key if autoInc
					return;
				}
			}
		}

		protected bool Update(out string message, Database db, DbTransaction trans)
		{
			message = "";
			StringBuilder sb = new StringBuilder();

			//sql update
			string[] exclude = { "CreatedBy", "CreatedWhen" };
			string sqlUpdate = Forms.DataUtils.GetSqlUpdateStatment(this._tableSchema, exclude, this._formInfo.TableName);

			//key fields do use parameters
			string where = Forms.DataUtils.GetWhereStatement(this._fcManager.TableKeysOrdered);
			sqlUpdate += " " + where;

			//sql parameters
			SqlParameter[] aParams = Forms.DataUtils.GetSqlParameters(exclude, true, this._tableSchema);

			//assign parameters
			AssignParameters(aParams);

			try
			{
				DbCommand cmd = db.GetSqlStringCommand(sqlUpdate);
				DataAccess.AddParamArrayToDbCommand(cmd, aParams);

				int i = db.ExecuteNonQuery(cmd, trans);
			}
			catch (Exception ex)
			{
				//bool b = ////ExceptionPolicy.HandleException(ex, "Exception Policy");
				sb.Append("Form could not be saved.");
				sb.Append(Environment.NewLine);
				sb.Append("Error message: " + ex.Message);
				message = sb.ToString();
				return false;
			}
			return true;
		}

		protected virtual bool AssignParameters(SqlParameter[] aParams)
		{
			string fieldName = "";

			foreach (SqlParameter param in aParams)
			{
				fieldName = param.SourceColumn;
				if (!_fcManager.Contains(fieldName))
					continue;

				FieldContext fc = (FieldContext)this._fcManager.Item(fieldName);

				//These don't have controls but we want to assign a value
				if (fc.Control == null)
				{
					if (fieldName.Equals("ModifiedBy"))
						((IDataParameter)param).Value = LoginForm.ApplicationSecurity.ApplicationUser.Name;
					else if (fieldName.Equals("ModifiedWhen"))
						((IDataParameter)param).Value = DateTime.Today;
					else if (fieldName.Equals("CreatedBy"))
						((IDataParameter)param).Value = LoginForm.ApplicationSecurity.ApplicationUser.Name;
					else if (fieldName.Equals("CreatedWhen"))
						((IDataParameter)param).Value = DateTime.Today;
					else
						((IDataParameter)param).Value = System.DBNull.Value;
					continue;
				}
				else
				{
					if (param.DbType.ToString() == "DateTime")
					{
						if (fc.CurrentValue != System.DBNull.Value)
							param.Value = ((DateTime)fc.CurrentValue).ToShortDateString();
						else
							param.Value = fc.CurrentValue;

					}
					else
						param.Value = fc.CurrentValue;
					Console.WriteLine(fieldName + " value: " + param.Value.ToString());
				}

			}
			return true;
		}

		protected virtual bool VerifyAll()
		{
			StringBuilder sb = new StringBuilder();
			MethodInfo mi = null;
			Object[] args = new Control[1];

			//this tells GetMethod what type of methods to look for
			BindingFlags bf = BindingFlags.NonPublic | BindingFlags.Instance;//| BindingFlags.DeclaredOnly; 

			foreach (FieldContext fc in this._fcManager.Items)
			{
				if (fc.Control == null)
					continue;
				if (fc.VerifyName.Length == 0)
					continue;
                if (fc.IsRequired == false)
                    continue;
				args[0] = fc.Control;
				mi = this.GetType().GetMethod(fc.VerifyName.Trim(), bf);
				if (mi == null)
				{
					sb.Append("Could not save form:");
					sb.Append(Environment.NewLine);
					if (fc.Labels == null)
						sb.Append("Field: " + fc.Column.ColumnName);
					else
						sb.Append("Field: " + fc.Labels.Label);
					sb.Append(Environment.NewLine);
					sb.Append("The VerifyName: " + fc.VerifyName + " was not found.");
					sb.Append(Environment.NewLine);
					sb.Append(Constants.NotifySupportImmediate);
					Exception ex = new Exception(sb.ToString());
					//bool b = ////ExceptionPolicy.HandleException(ex, "Exception Policy");
					MessageBox.Show(this._form, sb.ToString(), "Data Validation Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
					return false;
				}
				if (!(bool)mi.Invoke(this, args))
				{
					//Microsoft.VisualBasic.Interaction.Beep();
					sb.Append("Could not save form:");
					sb.Append(Environment.NewLine);
					if (fc.Labels == null)
						sb.Append("Field: " + fc.Column.ColumnName);
					else
						sb.Append("Field: " + fc.Labels.Label);
					sb.Append(Environment.NewLine);
					sb.Append("Warning: " + fc.ErrorMessage);

                    MessageBox.Show(this._form, sb.ToString(), "Data Validation Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
					CheckErrorStatus(false, fc);
					fc.Control.Focus();
					return false;
				}
				CheckErrorStatus(true, fc);
			}

			return true;
		}
		#endregion save

		#region events
		protected void fgbl_GridColumnValueChanged(object sender, EventArgs e)
		{
			if (this._formMode == EditMode.Edit || this._formMode == EditMode.New)
				_form.btnSave.Enabled = true;
		}

		protected void fgbl_GridValidateError(object sender, BLGridValidateErrorEventArgs e)
		{
			this._form.errP.SetError(e.Control, e.Message);
		}

		public virtual void Central_TextChanged(object sender, System.EventArgs e)
		{
			Control ctl = (Control)sender;
			Console.WriteLine("Central_TextChanged,Control: " + ctl.Name);
			Console.WriteLine("FormMode: " + this._formMode.ToString());
			if (this._formMode == EditMode.Edit || this._formMode == EditMode.New)
				_form.btnSave.Enabled = true;
		}

		public void Central_CheckedChanged(object sender, System.EventArgs e)
		{
			if (this._formMode == EditMode.Edit || this._formMode == EditMode.New)
				_form.btnSave.Enabled = true;
		}

		public void Central_ValueChanged(object sender, System.EventArgs e)
		{
			if (this._formMode == EditMode.Edit || this._formMode == EditMode.New)
			{
				_form.btnSave.Enabled = true;
			}
		}

		public void Central_SelectedIndexChanged(object sender, System.EventArgs e)
		{
			if (this._formMode == EditMode.Edit || this._formMode == EditMode.New)
				_form.btnSave.Enabled = true;
		}

		public virtual void Central_Validating(object sender, System.ComponentModel.CancelEventArgs e)
		{
			Control ctl = (Control)sender;
			Console.WriteLine("Central_Validating,Control: " + ctl.Name);
			FieldContext fc = (FieldContext)ctl.Tag;

			//We need a way to mark the form data as dirty and one way is to 
			//use the dataRow.  By changing a column value in the dataRow the 
			//dataRow.RowState will change.  So if the dataRowState is not 
			//'Unchanged' then the data is dirty.
			//One caveat to changing the dataRow is the state will change even
			//if you assign the same data as the original value.  So we have to
			//check for that

			//IsRowDirty does return true if this is a new row
			if ((!this._fcManager.IsRowDirty) && (!fc.IsColumnChanged(fc.Column.ColumnName)))
			{
				//do nothing here, however we want to continue
				//for any validations to be done
			}
			else
			{
				if (this._fcManager.CurrentRow.RowState == DataRowState.Added)
				{
					if (fc.Manager.CurrentRow[fc.Column.ColumnName] == System.DBNull.Value)
					{
						if (fc.CurrentValue != System.DBNull.Value)
							fc.Manager.CurrentRow[fc.Column.ColumnName] = fc.CurrentValue;
					}
					else
					{
						fc.Manager.CurrentRow[fc.Column.ColumnName] = fc.CurrentValue;
					}
				}
				else
					//we can assign a value to the data row and change its state	
					fc.Manager.CurrentRow[fc.Column.ColumnName] = fc.CurrentValue;
			}

			//check config setting to see if we should do field validation 
			if (!this._doFieldValidate)
				return;

			//don't know if we really need this, just a precation
			//only validate if the form is in edit or new mode
			if (!(this._formMode == EditMode.New || this._formMode == EditMode.Edit))
				return;

			Console.WriteLine("VerifyMethod: " + fc.VerifyName);

			//check to see if there is a validation method to call
			if (fc.VerifyName.Length == 0)
				return;

			//use reflection to call verify method
			//this tells GetMethod what type of methods to look for
			BindingFlags bf = BindingFlags.NonPublic | BindingFlags.Instance;
			MethodInfo mi = this.GetType().GetMethod(fc.VerifyName, bf);
			if (mi == null)
				return;

			Object[] args = new Control[1];
			args[0] = fc.Control;

			bool b = (bool)mi.Invoke(this, args);

			//this will display an error icon with error message if necessary
			CheckErrorStatus(b, fc);
			//this will enable/disable the btnSave
			//note: even though the change events enable btnSave, the user could 
			//re-enter the original value so that the rowState remains unchanged.
			//In that case we can disable the save button.
			CheckRowState();
		}
		#endregion events

		#region Validate
		protected virtual bool VerifyText(Control ctl)
		{
			bool retVal = true;
			FieldContext fc = (FieldContext)ctl.Tag;

			Console.WriteLine("VerifyText,Control: " + ctl.Name);

			if (fc.Manager.CurrentRow == null)
				return true;

			Console.WriteLine("CurrentValue: " + fc.CurrentValue.ToString());

			if (ctsu.Admin.Forms.Utils.IsMissingValue(ctl))
			{
				if (fc.IsRequired)
				{
					fc.ErrorMessage = Constants.ValidErrorRequiredEmpty;
					retVal = false;
				}
			}

			Console.WriteLine("Column Changed = " + fc.IsColumnChanged(fc.Column.ColumnName).ToString());

			Console.WriteLine("ErrorMessage: " + fc.ErrorMessage);
			Console.WriteLine("Return Value: " + retVal.ToString());

			return retVal;
		}

		protected virtual bool VerifyInt(Control ctl)
		{
			bool retVal = true;
			FieldContext fc = (FieldContext)ctl.Tag;

			Console.WriteLine("VerifyText,Control: " + ctl.Name);

			if (fc.Manager.CurrentRow == null)
				return true;

			Console.WriteLine("CurrentValue: " + fc.CurrentValue.ToString());

			if (ctsu.Admin.Forms.Utils.IsMissingValue(ctl))
			{
				if (fc.IsRequired)
				{
					fc.ErrorMessage = Constants.ValidErrorRequiredEmpty;
					retVal = false;
				}
			}

			//range
			if (fc.Range.Length > 0)
			{
				//must be posative
				if (fc.Range == ">0")
				{
					if (!((int)fc.CurrentValue > 0))
					{
						fc.ErrorMessage = Constants.ValidErrorRangeGreaterThanZero;
						retVal = false;
					}
				}
			}

			Console.WriteLine("Column Changed = " + fc.IsColumnChanged(fc.Column.ColumnName).ToString());

			Console.WriteLine("ErrorMessage: " + fc.ErrorMessage);
			Console.WriteLine("Return Value: " + retVal.ToString());

			return retVal;
		}

		protected virtual bool VerifyBool(Control ctl)
		{
			bool retVal = true;
			CheckBox chk = (CheckBox)ctl;
			FieldContext fc = (FieldContext)ctl.Tag;

			Console.WriteLine("VerifyBool,Control: " + ctl.Name);

			if (fc.Manager.CurrentRow == null)
				return true;

			Console.WriteLine("CurrentValue: " + fc.CurrentValue.ToString());

			Console.WriteLine("Column Changed = " + fc.IsColumnChanged(fc.Column.ColumnName).ToString());

			Console.WriteLine("ErrorMessage: " + fc.ErrorMessage);
			Console.WriteLine("Return Value: " + retVal.ToString());

			return retVal;
		}

		protected virtual bool VerifyCombo(Control ctl)
		{
			bool retVal = true;
			ComboBox cbo = (ComboBox)ctl;
			FieldContext fc = (FieldContext)ctl.Tag;

			Console.WriteLine("VerifyCombo,Control: " + ctl.Name);

			if (fc.Manager.CurrentRow == null)
				return true;

			Console.WriteLine("CurrentValue: " + fc.CurrentValue.ToString());

			if ((int)fc.CurrentValue == -9)
			{
				if (fc.IsRequired)
				{
					fc.ErrorMessage = Constants.ValidErrorRequiredEmpty;
					retVal = false;
				}

			}
			else
			{
				fc.ErrorMessage = "";
			}

			Console.WriteLine("Column Changed = " + fc.IsColumnChanged(fc.Column.ColumnName).ToString());

			Console.WriteLine("ErrorMessage: " + fc.ErrorMessage);
			Console.WriteLine("Return Value: " + retVal.ToString());

			return retVal;
		}

		protected virtual bool VerifyDate(Control ctl)
		{
			bool retVal = true;
			DateTimePickerAdv dtp = (DateTimePickerAdv)ctl;
			FieldContext fc = (FieldContext)ctl.Tag;

			Console.WriteLine("VerifyDate,Control: " + ctl.Name);

			if (fc.Manager.CurrentRow == null)
				return true;

			Console.WriteLine("CurrentValue: " + fc.CurrentValue.ToString());

			if (fc.CurrentValue == System.DBNull.Value)
			{
				if (fc.IsRequired)
				{
					fc.ErrorMessage = Constants.ValidErrorRequiredEmpty;
					retVal = false;
				}
			}
			else
			{
				fc.ErrorMessage = "";
			}

			Console.WriteLine("Column Changed = " + fc.IsColumnChanged(fc.Column.ColumnName).ToString());

			Console.WriteLine("ErrorMessage: " + fc.ErrorMessage);
			Console.WriteLine("Return Value: " + retVal.ToString());

			return retVal;
		}

		//only used by Central_Validating
		public void CheckErrorStatus(bool valid, FieldContext fc)
		{
			if (valid)
				this._form.errP.SetError(fc.ErrorControl, "");
			else
			{
				Microsoft.VisualBasic.Interaction.Beep();
				this._form.errP.SetError(fc.ErrorControl, fc.ErrorMessage);
			}
		}

		public void ClearErrorStatus(FieldContext fc)
		{
			this._form.errP.SetError(fc.ErrorControl, "");
		}

		private void CheckRowState()
		{
			if (_fcManager.CurrentRow.RowState == DataRowState.Unchanged)
				this._form.btnSave.Enabled = false;
			else
				this._form.btnSave.Enabled = true;

			Console.WriteLine("RowState: " + _fcManager.CurrentRow.RowState.ToString());
		}
		#endregion Validate

		protected virtual void _fcManager_OnAfterCreateFieldContexts()
		{
			Console.WriteLine("_fcManager_OnAfterCreateFieldContexts virtual");
		}

		private void _fcManager_OnAfterBindFieldContextsToControls()
		{
			Console.WriteLine("_fcManager_OnAfterBindFieldContextsToControls virtual");
		}

		private void _fcManager_OnAfterLoadMetaDataEvents()
		{
			Console.WriteLine("_fcManager_OnAfterLoadMetaDataEvents virtual");
		}
		protected virtual void _vcManager_OnAfterHookEvents()
		{
			Console.WriteLine("_vcManager_OnAfterHookEvents virtual");
		}

		protected virtual void FormOptions_OnOptionsChanged(OptionsChangedArgs oca)
		{
			Console.WriteLine("FormOptions_OnOptionsChanged:\nOption: " +
				oca.Option + "\nold value: " + oca.OldValue.ToString() +
				"\nnew value: " + oca.NewValue.ToString());
			switch (oca.Option)
			{
				case "FieldValidate":
					this._doFieldValidate = bool.Parse((string)oca.NewValue);
					break;
				case "SummaryValidate":
					this._doSummaryValidate = bool.Parse((string)oca.NewValue);
					break;

			}
		}

	}
}
